//
//  ATHttpTool.m
//  CoderLT
//
//  Created by CoderLT on 2017/5/22.
//  Copyright © 2017年 CoderLT. All rights reserved.
//

#import "ATHttpTool.h"
#import <AFNetworking/AFNetworking.h>
#import <AFNetworking/AFNetworkActivityIndicatorManager.h>

@interface ATHttpTool ()
@property (nonatomic, strong) YYReachability *reachability;
@property (nonatomic, copy, readonly) NSString *networkType;
@end
@implementation ATHttpTool
static ATHttpTool *_instance;
+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}
- (YYReachability *)reachability {
    if (!_reachability) {
        _reachability = [YYReachability reachability];
    }
    return _reachability;
}
+ (YYReachability *)reachability {
    return [ATHttpTool sharedInstance].reachability;
}
+ (BOOL)reachable {
    return [ATHttpTool reachability].status != YYReachabilityStatusNone;
}
+ (BOOL)reachableWWAN {
    return [ATHttpTool reachability].status == YYReachabilityStatusWWAN;
}
+ (BOOL)reachableWifi {
    return [ATHttpTool reachability].status == YYReachabilityStatusWiFi;
}
+ (NSString *)networkType {
    NSString * string = @"";
    YYReachabilityStatus netState = [ATHttpTool reachability].status;
    switch (netState) {
        case YYReachabilityStatusNone: {
            string = @"";
            break;
        }
        case YYReachabilityStatusWiFi: {
            string = @"WIFI";
            break;
        }
        case YYReachabilityStatusWWAN: {
            YYReachabilityWWANStatus netStateWWAN = [YYReachability reachability].wwanStatus;
            switch (netStateWWAN) {
                case YYReachabilityWWANStatus2G:
                    string = @"2G";
                    break;
                case YYReachabilityWWANStatus3G:
                    string = @"3G";
                    break;
                case YYReachabilityWWANStatus4G:
                    string = @"4G";
                    break;
                default:
                    break;
            }
            break;
        }
        default:
            break;
    }
    return string;
}


#pragma mark - 接口请求
+ (NSURLSessionDataTask *)GET:(NSString *)urlString params:(id)params success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *))failure {
    return [self method:ATHttpMethodGet urlString:urlString params:params bodyBlock:nil progress:nil success:success failure:failure];
}
+ (NSURLSessionDataTask *)PUT:(NSString *)urlString params:(id)params success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *errorMsg))failure {
    return [self method:ATHttpMethodPut urlString:urlString params:params bodyBlock:nil progress:nil success:success failure:failure];
}
+ (NSURLSessionDataTask *)DELETE:(NSString *)urlString params:(id)params success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *errorMsg))failure {
    return [self method:ATHttpMethodDelete urlString:urlString params:params bodyBlock:nil progress:nil success:success failure:failure];
}
+ (NSURLSessionDataTask *)POST:(NSString *)urlString params:(id)params success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *))failure {
    return [self POST:urlString params:params bodyBlock:nil success:success failure:failure];
}
+ (NSURLSessionDataTask *)POST:(NSString *)urlString params:(id)params bodyBlock:(void (^)(id<AFMultipartFormData>))block success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *))failure {
    return [self POST:urlString params:params bodyBlock:block progress:nil success:success failure:failure];
}
+ (NSURLSessionDataTask *)POST:(NSString *)urlString params:(id)params bodyBlock:(void (^)(id<AFMultipartFormData>))block progress:(void (^)(NSProgress *))progress success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *))failure {
    return [self method:ATHttpMethodPost urlString:urlString params:params bodyBlock:block progress:progress success:success failure:failure];
}
+ (NSURLSessionDataTask *)method:(ATHttpMethod)method urlString:(NSString *)urlString params:(id)params bodyBlock:(void (^)(id<AFMultipartFormData>))block progress:(void (^)(NSProgress *))progress success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *))failure {
    return [self method:method urlString:urlString params:params exParams:nil config:nil bodyBlock:block progress:progress success:success failure:failure];
}
+ (NSURLSessionDataTask *)method:(ATHttpMethod)method urlString:(NSString *)urlString params:(id)params exParams:(NSDictionary *)exParams config:(void (^)(AFHTTPSessionManager *))config bodyBlock:(void (^)(id<AFMultipartFormData>))block progress:(void (^)(NSProgress *))progress success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSString *))failure {
    return [self manager:nil method:method urlString:urlString params:params exParams:nil bodyBlock:block progress:progress completion:^(NSURLSessionDataTask *task, id responseObject, NSError *error) {
        if (error) {
            !failure ?: failure(error.localizedFailureReason ?: @"无网络链接, 请检查网络设置");
        }
        else {
            !success ?: success(task, responseObject);
        }
    }];
}

+ (NSURLSessionDataTask *)manager:(AFHTTPSessionManager *)manager method:(ATHttpMethod)method urlString:(NSString *)urlString params:(id)params exParams:(NSDictionary *)exParams bodyBlock:(void (^)(id<AFMultipartFormData>))block progress:(void (^)(NSProgress *))progress completion:(void (^)(NSURLSessionDataTask *, id, NSError *))completion {
    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
    [[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount];
    
    if (!manager) {
        manager = [[AFHTTPSessionManager alloc] init];
        manager.responseSerializer = [AFJSONResponseSerializer serializer];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/plain", @"text/html", nil];
    }
    manager.requestSerializer.timeoutInterval = manager.requestSerializer.timeoutInterval ?: ATHttpToolDefaultTimeoutInterval;
    
    void (^successBlock)(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) = ^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];
        ATHttpLog(@"%@ :: %@ %@ ==> %@", method, task.originalRequest.URL, params, responseObject);
        !completion ?: completion(task, responseObject, nil);
    };
    void (^failureBlock)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];
        ATHttpLog(@"%@ :: %@ %@ ==> %@", method, task.originalRequest.URL, params, error);
        !completion ?: completion(task, nil, error);
    };
    
    switch (method) {
        case ATHttpMethodGet: {
            return [manager GET:urlString parameters:params progress:progress success:successBlock failure:failureBlock];
        }
        case ATHttpMethodPut: {
            return [manager PUT:urlString parameters:params success:successBlock failure:failureBlock];
        }
        case ATHttpMethodDelete: {
            return [manager DELETE:urlString parameters:params success:successBlock failure:failureBlock];
        }
        case ATHttpMethodPost: {
            if (!block) {
                return [manager POST:urlString parameters:params progress:progress success:successBlock failure:failureBlock];
            }
            else {
                return [manager POST:urlString parameters:params constructingBodyWithBlock:block progress:progress success:successBlock failure:failureBlock];
            }
        }
        default:
            break;
    }
    return nil;
}
@end
